package com.csu.service.serviceImpl;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.csu.common.CommonResponse;
import com.csu.entity.*;
import com.csu.mapper.*;
import com.csu.service.RedisService;
import com.csu.service.UserService;
import com.csu.vo.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {
    //缓存键值对过期时间（毫秒）
    private static final long duration = 30L;
    private static final ObjectMapper mapper = new ObjectMapper();
    private static final String auditPicturePath = "http://106.53.100.120:80/img/msb.jpg";

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private AuditMapper auditMapper;

    @Autowired
    private ClassesMapper classesMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private ParentStudentMapper parentStudentMapper;

    @Autowired
    private SubjectMapper subjectMapper;
    @Autowired
    private UserHeadPictureMapper userHeadPictureMapper;
    @Autowired
    private AuditHeadPictureMapper auditHeadPictureMapper;

    @Autowired
    private RedisService redisService;



    /**
     *登录功能
     */
    @Override
    public CommonResponse<Object> login(String accountName, String password) {
        //通过accountName找到username
        String username = userMapper.getUsernameByAccountName(accountName);

        //先查询审核表
        if(auditMapper.getAuditByAccountName(accountName) != null) {
            return CommonResponse.createForError("审核中");
        }
        //再看账号名和密码是否正确
        if (userMapper.getUserByAccountNameAndPassword(accountName, password) != null) {
            //登录成功则返回tokenInfo和用户信息
            LoginRespVO loginRespVO = userMapper.getLoginInfoByAccountName(accountName);

            //将SaTokenInfo传给前端
            StpUtil.login(userMapper.getIdByAccountName(accountName));

            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            loginRespVO.setSaTokenInfo(tokenInfo);
            loginRespVO.setUsername(username);
            loginRespVO.setImgurl(userHeadPictureMapper.getHeadPicture(loginRespVO.getUserId()));

            System.out.println("loginId:" + StpUtil.getLoginIdAsInt());

            return CommonResponse.createForSuccess("SUCCESS", loginRespVO);
        }
        return CommonResponse.createForError("账号或密码错误");
    }


    /**
     *查找class_id为一定值的所有学生（存入缓存）
     */
    @Override
    public CommonResponse<List<UserVo>> getStudents(int classId) throws JsonProcessingException {
        //先从缓存中查找，看能不能找到，如果查不到则存到缓存中，找到则直接返回
        //初始化连接池，获取Jedis对象
        RedisConnection.init();
        Jedis jedis = RedisConnection.getJedis();
        //从Redis中获取JSON字符串
        String jsonFromRedis = jedis.get("classId" + classId);
        //若查找到则直接返回
        if(!(jsonFromRedis == null || jsonFromRedis.isEmpty())){
            //将JSON字符串反序列化成List<User>
            List<UserVo> userListFromRedis = mapper.readValue(jsonFromRedis, new TypeReference<List<UserVo>>() {});
            RedisConnection.close(jedis);
            return CommonResponse.createForSuccess("SUCCESS", userListFromRedis);
        }

        //若没找到，则正常进行查找，然后将其存入Redis缓存
        List<User> studentList = userMapper.getStudentsByClassId(classId);
        List<UserVo> userVos = new ArrayList<>();
        for (User user : studentList){
            UserVo userVo = new UserVo();
            userVo.setAccountName(user.getAccountName());
            userVo.setPassword(user.getPassword());
            userVo.setRoleId(user.getRoleId());
            userVo.setClassId(user.getClassId());
            userVo.setUserId(user.getUserId());
            userVo.setUsername(user.getUsername());
            userVo.setImgurl(userHeadPictureMapper.getHeadPicture(user.getUserId()));
            userVos.add(userVo);
        }
        if(!userVos.isEmpty()){
            //存入缓存
            //将studentList序列化成json字符串
            String json = mapper.writeValueAsString(userVos);
            //将json字符串存入Redis中
            //jedis.set("classId" + classId, json, new SetParams().px(300000L));
            jedis.set("classId" + classId, json, new SetParams().px(duration));

            RedisConnection.close(jedis);
            return CommonResponse.createForSuccess("SUCCESS", userVos);
        }
        RedisConnection.close(jedis);
        return CommonResponse.createForError("未查询到结果");
    }

    /**
     *获取班级列表
     */
    @Override
    public CommonResponse<List<ClassesRespVO>> getClasses() throws JsonProcessingException {
        List<ClassesRespVO> classesRespVOList =new ArrayList<>();
        //初始化连接池，获取Jedis对象
        RedisConnection.init();
        Jedis jedis = RedisConnection.getJedis();
        //从Redis中获取json字符串
        String jsonFromRedis = jedis.get("classes");
        //若查到则直接返回
        if(!(jsonFromRedis == null || jsonFromRedis.isEmpty())){
            //将json字符串反序列化成List<Classes>
            List<ClassesRespVO> classesListFromRedis = mapper.readValue(jsonFromRedis, new TypeReference<List<ClassesRespVO>>() {});
            RedisConnection.close(jedis);
            return CommonResponse.createForSuccess("SUCCESS", classesListFromRedis);
        }

        //没从redis中查到则正常查询
        List<Classes> classesList = classesMapper.getClasses();
        if(!classesList.isEmpty()){
            for(Classes classes: classesList){
                ClassesRespVO classesRespVO = new ClassesRespVO();
                classesRespVO.setClassId(classes.getClassId());
                classesRespVO.setClassName(classes.getClassName());
                classesRespVO.setClassStatus(classes.getClassStatus());
                //将classes变成classesResp,增加一个总人数
                int studentNum = userMapper.getNumByClassId(classes.getClassId());
                classesRespVO.setNumber(studentNum);
                classesRespVOList.add(classesRespVO);
            }

            //将classesList序列化成json字符串
            String json = mapper.writeValueAsString(classesRespVOList);
            jedis.set("classes", json, new SetParams().px(30L));
            RedisConnection.close(jedis);
            return CommonResponse.createForSuccess("SUCCESS", classesRespVOList);
        }
        RedisConnection.close(jedis);
        return CommonResponse.createForError("未查询到结果");
    }

    /**
    * role_id:学生（3），家长（2），老师（1），管理员（0）
    *注册：家长，老师放审核表；学生，管理员放user表, 家长才有一个学生id
    */
    @Override
    public CommonResponse<Object> register(int classId, String password, int roleId, String accountName, int studentId, int subjectId) {
        //找到user表和audit表中最大id值，加一进行插入
        int maxUserId = userMapper.getMaxUserId();
        int maxAuditId = auditMapper.getMaxAuditId();
        int insertId = Math.max(maxUserId, maxAuditId) + 1;

        //判断accountId是否重复（user表和audit表）
        Set<String> accountNameSet = new HashSet<>();
        List<String> auditAccountNameList = auditMapper.getAccountNameList();
        List<String> userAccountNameList = userMapper.getAccountNameList();
        //将audit表和user表的accountName加到set集合中
        accountNameSet.addAll(auditAccountNameList);
        accountNameSet.addAll(userAccountNameList);
        //判断是否有重复值
        if(accountNameSet.contains(accountName))
            return CommonResponse.createForError("已存在改用户名，请重新命名");

        //无重复用户名则继续
        if (roleId == 1){
            //老师插入审核表，无学生id
            int teacherRows = auditMapper.insertTeacher(insertId, accountName, password, roleId, classId, subjectId);
            int teacherPictureRows = auditHeadPictureMapper.insertPicture(insertId, auditPicturePath);
            if (teacherRows != 0 && teacherPictureRows != 0){
                return CommonResponse.createForSuccess("老师插入成功", null);
            }
            return CommonResponse.createForError("老师插入失败");
        } else if (roleId == 2) {
            //家长插入审核表，有学生id
            int parentRows = auditMapper.insertParent(insertId, accountName, password, roleId, classId, studentId);
            int parentPictureRows = auditHeadPictureMapper.insertPicture(insertId, auditPicturePath);
            if (parentRows != 0){
                return CommonResponse.createForSuccess("家长插入成功", null);
            }
            return CommonResponse.createForError("家长插入失败");
        } else if(roleId == 0 || roleId == 3){
            //管理员，学生直接插入user表
            switch (roleId){
                case 0:{
                    int userRows = userMapper.insertUser(insertId, accountName, password, roleId, 0);
                    int userPictureRows = userHeadPictureMapper.insertPicture(insertId, auditPicturePath);
                    if (userRows != 0 && userPictureRows != 0)
                        return CommonResponse.createForSuccess("管理员插入成功", null);
                    return CommonResponse.createForError("插入失败");
                }
                case 3:{
                    int userRows = userMapper.insertUser(insertId, accountName, password, roleId, classId);
                    int userPictureRows = userHeadPictureMapper.insertPicture(insertId, auditPicturePath);
                    if (userRows != 0 && userPictureRows != 0)
                        return CommonResponse.createForSuccess("学生插入成功", null);
                    return CommonResponse.createForError("插入失败");
                }
                default:
                    return  CommonResponse.createForError("未知角色");
            }
        }
        return CommonResponse.createForError("role_id错误");
    }

    /**
     *改用户名
     */
    @Override
    public CommonResponse<Object> changeUsername(String name, int id) {
        int rows = userMapper.changeUsername(name, id);
        if(rows != 0)
            return CommonResponse.createForSuccess("修改用户名成功！", null);
        return CommonResponse.createForError("修改用户名失败");
    }

    /**
     *改密码
     */
    @Override
    public CommonResponse<Object> changePassword(String password, int id) {
        int rows = userMapper.changePassword(password, id);
        if(rows != 0)
            return CommonResponse.createForSuccess("修改密码成功！", null);
        return CommonResponse.createForError("修改密码失败");
    }

    /**
     *
     * @param classId
     * @return List<ClassMemberVo>
     * 取出与当前用户同班的学生列表
     */
    @Override
    public List<ClassMemberVo> getClassMember(int classId) {
        List<User> users = userMapper.getUserListByClassId(classId);
        return UserToClassMemberVo(users);
    }

    /**
     * 把User转化为ClassMemberVo，方便前后端数据传输
     * @param users
     * @return
     */
    List<ClassMemberVo> UserToClassMemberVo(List<User> users){
        List<ClassMemberVo> classMemberVos = new ArrayList<>();
        for (User user : users){
            ClassMemberVo classMemberVo = new ClassMemberVo();
            classMemberVo.setUsername(user.getUsername());
            classMemberVo.setUserId(user.getUserId());
            classMemberVo.setRoleName(roleMapper.getRoleNameByRoleId(user.getRoleId()));
            classMemberVo.setChecked(false);
            classMemberVo.setImgurl(userHeadPictureMapper.getHeadPicture(user.getUserId()));
            classMemberVos.add(classMemberVo);
        }
        return classMemberVos;
    }

    /**
     * 获取待审核的家长列表
     */
    @Override
    public CommonResponse<List<AuditVo>> getAuditParents(int id) {
        //根据老师id查找对应的班级
        Integer classId = userMapper.getClassIdByUserId(id);
        if(classId == null)
            return CommonResponse.createForError("查询失败，无对应班级");
        //根据班级id查找audit表中家长列表
        List<Audit> parentsList = auditMapper.getParentsListByClassId(classId);
        List<AuditVo> auditVos = new ArrayList<>();
        for (Audit audit : parentsList){
            AuditVo auditVo = new AuditVo();
            auditVo.setAccountName(audit.getAccountName());
            auditVo.setAuditId(audit.getAuditId());
            auditVo.setPassword(audit.getPassword());
            auditVo.setStudentId(audit.getStudentId());
            auditVo.setRoleId(audit.getRoleId());
            auditVo.setClassId(audit.getClassId());
            auditVo.setImgurl(auditHeadPictureMapper.getAuditHeadPicture(audit.getAuditId()));
            auditVos.add(auditVo);
        }

        if(!parentsList.isEmpty()){
            return CommonResponse.createForSuccess("查询成功", auditVos);
        }
        return CommonResponse.createForError("查询失败");
    }

    /**
     * 获取待审核的老师列表
     */
    @Override
    public CommonResponse<List<AuditVo>> getAuditTeachers(){
        List<Audit> auditList = auditMapper.getAuditTeacherList();
        List<AuditVo> auditVos = new ArrayList<>();
        for (Audit audit : auditList){
            AuditVo auditVo = new AuditVo();
            auditVo.setAccountName(audit.getAccountName());
            auditVo.setAuditId(audit.getAuditId());
            auditVo.setPassword(audit.getPassword());
            auditVo.setStudentId(audit.getStudentId());
            auditVo.setRoleId(audit.getRoleId());
            auditVo.setClassId(audit.getClassId());
            auditVo.setImgurl(auditHeadPictureMapper.getAuditHeadPicture(audit.getAuditId()));
            auditVos.add(auditVo);
        }

        if(!auditList.isEmpty()){
            return CommonResponse.createForSuccess("查询成功", auditVos);
        }
        return CommonResponse.createForError("查询失败");
    }

    /**
     * 审核不通过，删除第audit_id条审核信息
     */
    @Override
    public CommonResponse<Object> deleteAudit(int id){
        int rows = auditMapper.deleteAudit(id);
        int pictureRows = auditHeadPictureMapper.deletePicture(id);
        if(rows != 0 && pictureRows != 0){
            return CommonResponse.createForSuccess("删除成功", null);
        }
        return CommonResponse.createForError("删除失败");
    }

    /**
     * 第id条信息审核通过，添加用户信息到user,PS等。
     */
    public CommonResponse<Object> passAudit(int auditId){
        //先根据id获取audit对象和auditHeadPicture对象
        Audit audit = auditMapper.getAuditByAuditId(auditId);
        AuditHeadPicture auditHeadPicture = auditHeadPictureMapper.getAuditHeadPictureById(auditId);
        //从audit表和auditPicture表中删除
        int pictureRows = auditHeadPictureMapper.deletePicture(auditId);
        int rows = auditMapper.deleteAudit(auditId);
        if(rows != 0 && pictureRows != 0){
            switch(audit.getRoleId()){
                //身份为老师时，插入到user表
                case 1:{
                    int row1 = userMapper.insertUserByUserId(audit.getAuditId(), audit.getAccountName(), audit.getPassword(),
                            audit.getRoleId(), audit.getClassId());
                    int pictureRows1 = userHeadPictureMapper.insertPicture(auditId, auditHeadPicture.getAuditPicturePath());
                    if(row1 != 0 && pictureRows1 != 0)
                        return CommonResponse.createForSuccess("老师通过审核", null);
                    return CommonResponse.createForError("通过审核失败");
                }
                //身份为家长时，插入到user表和parent_student表
                case 2:{
                    int row2 = userMapper.insertUserByUserId(audit.getAuditId(), audit.getAccountName(), audit.getPassword(),
                            audit.getRoleId(), audit.getClassId());
                    int pictureRows2 = userHeadPictureMapper.insertPicture(auditId, auditHeadPicture.getAuditPicturePath());
                    int row3 = parentStudentMapper.insertPS(audit.getAuditId(), audit.getStudentId());
                    if(row2 != 0 && row3 != 0 && pictureRows2 != 0)
                        return CommonResponse.createForSuccess("家长通过审核", null);
                    return CommonResponse.createForError("通过审核失败");
                }
                //未知角色
                default:
                    return CommonResponse.createForError("未知角色");
            }
        }
        return CommonResponse.createForError("通过审核失败");
    }

    /**
     * 获取学科列表
     */
    public CommonResponse<List<Subject >> getSubjects(int classId){
        //先查询USER表中class_id有哪些subject_id，然后返回除开这几个subject_id的subject_id的信息
        List<Integer> subjectIdList = userMapper.getSubjectIdByClassId(classId);
    // 查询所有subject_id
        List<Integer> allSubjectIdList = subjectMapper.getAllSubjectId();
    // 使用Java 8 的Stream API过滤掉subjectIdList中包含的subjectId
        List<Integer> resultSubjectIdList = allSubjectIdList.stream()
                .filter(subjectId -> !subjectIdList.contains(subjectId))
                .collect(Collectors.toList());
    // 现在resultSubjectIdList 中包含所有不在subjectIdList 中的subjectId

        List<Subject> subjectList = new ArrayList<>();
        for (int subjectId: resultSubjectIdList){
            Subject subject = subjectMapper.getSubject(subjectId);
            subjectList.add(subject);
        }
        if(!subjectList.isEmpty())
            return CommonResponse.createForSuccess("SUCCESS", subjectList);
        return CommonResponse.createForError("ERROR");
    }

    /**
     * 通过userId获取username
     * @param userId
     * @return String
     */

    @Override
    public String getUsernameByUserId(int userId) {
        return userMapper.getUsernameById(userId);
    }

    /**
     * 获取孩子名字
     */
    @Override
    public CommonResponse<List<StudentRespVO>> getChildren(int userId){
        List<StudentRespVO> studentRespVOList = new ArrayList<>();
        //通过家长id找到学生id
        List<Integer> idList = parentStudentMapper.getChildrenIdList(userId);
        if (!idList.isEmpty()){
            //通过学生id找到学生名字
            for(int studentId: idList){
                StudentRespVO studentRespVO = new StudentRespVO();
                studentRespVO.setStudentID(studentId);
                String studentName = userMapper.getNameById(studentId);
                studentRespVO.setStudentName(studentName);
                studentRespVOList.add(studentRespVO);
            }
            return CommonResponse.createForSuccess("查询成功", studentRespVOList);
        }
        return CommonResponse.createForError("未查询到孩子信息");
    }

    /**
     * 获取身份ID
     * @param userId
     * @return Integer
     */

    @Override
    public Integer getRole(int userId) {
        return userMapper.getRoleIdByUserId(userId);
    }
}
